package com.mayisoftware.mayioa.business.plan.impl.serviceImpl;

import com.mayisoftware.mayioa.business.plan.api.constant.PlanCfgConstants;
import com.mayisoftware.mayioa.business.plan.api.domain.PlanConstraint;
import com.mayisoftware.mayioa.business.plan.api.service.IPlanConstraintService;
import com.mayisoftware.mayioa.business.plan.api.service.ObjectPropertyPredicate;
import com.mayisoftware.mayioa.business.plan.impl.dao.PlanConstraintMapper;
import com.mayisoftware.mayioa.business.score.api.domain.ScoreInfo;
import com.mayisoftware.mayioa.business.score.impl.dao.ScoreInfoMapper;
import com.mayisoftware.mayioa.common.api.annotation.DataScope;
import com.mayisoftware.mayioa.common.api.enums.FilterMode;
import com.mayisoftware.mayioa.common.api.enums.RuleTarget;
import com.mayisoftware.mayioa.common.impl.support.Convert;
import com.mayisoftware.mayioa.common.impl.utils.StringUtils;
import com.mayisoftware.mayioa.platform.api.domain.SysPost;
import com.mayisoftware.mayioa.platform.api.domain.SysUser;
import com.mayisoftware.mayioa.platform.impl.dao.SysDictDataMapper;
import com.mayisoftware.mayioa.platform.impl.dao.SysUserMapper;
import org.apache.commons.lang3.EnumUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 约束配置 业务层处理
 */
@Service
public class PlanConstraintServiceImpl implements IPlanConstraintService
{
    @Autowired
    private PlanConstraintMapper planConstraintMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ScoreInfoMapper scoreInfoMapper;

    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    /**
     * 根据条件分页查询约束配置对象
     * 
     * @param planConstraint 约束配置信息
     * @return 约束配置信息集合信息
     */
    @Override
    public List<PlanConstraint> selectPlanConstraintList(PlanConstraint planConstraint)
    {
        return planConstraintMapper.selectPlanConstraintList(planConstraint);
    }

    /**
     * 通过约束名查询约束配置
     *
     * @param planCstrName 约束名
     * @return 约束配置对象信息
     */
    @Override
    public PlanConstraint selectPlanConstraintByName(String planCstrName) {
        return planConstraintMapper.selectPlanConstraintByName(planCstrName);
    }

    /**
     * 通过计划ID查询约束配置
     *
     * @param planId 计划ID
     * @return 约束配置对象信息
     */
    @Override
    public List<PlanConstraint> selectPlanConstraintByPlanId(Long planId)
    {
        List<PlanConstraint> planConds = planConstraintMapper.selectPlanConstraintByPlanId(planId);
        List<PlanConstraint> conds = planConstraintMapper.selectPlanConstraintList(new PlanConstraint());
        for (PlanConstraint cond : conds)
        {
            for (PlanConstraint planCond : planConds)
            {
                if (cond.getPlanCstrId().longValue() == planCond.getPlanCstrId().longValue())
                {
                    cond.setFlag(true);
                    break;
                }
            }
        }
        return conds;
    }

    /**
     * 通过约束配置ID查询约束配置
     * 
     * @param planCstrId 约束配置ID
     * @return 约束配置对象信息
     */
    @Override
    public PlanConstraint selectPlanConstraintById(Long planCstrId)
    {

        return planConstraintMapper.selectPlanConstraintById(planCstrId);
    }

    /**
     * 通过约束配置ID删除约束配置
     *
     * @param planCstrId 约束配置ID
     * @return 结果
     */
    @Override
    public int deletePlanConstraintById(Long planCstrId) {

        return planConstraintMapper.deletePlanConstraintById(planCstrId);
    }

    /**
     * 批量删除约束配置信息
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deletePlanConstraintByIds(String ids) throws Exception
    {
        Long[] planCstrIds = Convert.toLongArray(ids);
        return planConstraintMapper.deletePlanConstraintByIds(planCstrIds);
    }

    /**
     * 新增约束配置信息
     * 
     * @param planConstraint 约束配置信息
     * @return 结果
     */
    @Override
    public int insertPlanConstraint(PlanConstraint planConstraint)
    {
        // 新增约束配置信息
        int rows = planConstraintMapper.insertPlanConstraint(planConstraint);
        return rows;
    }

    /**
     * 修改保存约束配置信息
     * 
     * @param planConstraint 约束配置信息
     * @return 结果
     */
    @Override
    public int updatePlanConstraint(PlanConstraint planConstraint)
    {
        return planConstraintMapper.updatePlanConstraint(planConstraint);
    }

    /**
     * 校验约束配置名称是否唯一
     * 
     * @param planConstraint 约束配置对象
     * @return
     */
    @Override
    public String checkPlanCstrNameUnique(PlanConstraint planConstraint)
    {
        Integer planCstrId = StringUtils.isNull(planConstraint.getPlanCstrId()) ? -1 : planConstraint.getPlanCstrId();

        PlanConstraint plan = planConstraintMapper.checkPlanCstrNameUnique(planConstraint.getPlanCstrObj());
        if (StringUtils.isNotNull(plan) && plan.getPlanCstrId().longValue() != planCstrId.longValue())
        {
            return PlanCfgConstants.PLANCFG_NAME_NOT_UNIQUE;
        }
        return PlanCfgConstants.PLANCFG_NAME_UNIQUE;
    }

    /**
     * 校验约束配置是否已使用
     */
    @Override
    public int checkPlanCstrIsUse(Long planCstrId)
    {
        return 0;
    }

    /**
     * 校验用户是否可以报名计划
     */
    @Override
    public String checkPlanIsCanEnter(Long planId, Long userId)
    {
        // 是否可以报名标识，默认为true，判断过程中有一项不满足设置为false，即可返回
        String resultMsg = PlanCfgConstants.SUCCESS;
        boolean flag = true;

        // 查询用户信息
        SysUser user = userMapper.selectUserById(userId);

        // 查询计划中当前用户绩效
//        List<ScoreInfo> scoreList = scoreInfoMapper.selectScoreListByUserAndPlanId(planId, userId);

        // 根据计划ID查询计划的约束
        List<PlanConstraint> planCstrList = planConstraintMapper.selectPlanConstraintByPlanId(planId);

        // 遍历计划约束信息，校验用户信息是否满足条件
        for (PlanConstraint rule : planCstrList)
        {

            RuleTarget ruleTarget = RuleTarget.getRuleEnumByValue(rule.getPlanCstrObj());
            switch(ruleTarget){
                // 项目角色 判断 用户的项目角色->约束规则->约束键值
                case PROJCET_ROLE:{
                    flag = checkRule(user.getProjectRole(),EnumUtils.getEnum(FilterMode.class,rule.getPlanCstrRule()),rule.getPlanCstrValue());
                    if(!flag)
                    {
                        resultMsg = getResultMsg(rule);
                    }
                    break;
                }
                // 岗位级别 判断 用户的岗位级别->约束规则->约束键值
                case USER_POST:{
                    flag = checkRule(user.getHwLevel(),EnumUtils.getEnum(FilterMode.class,rule.getPlanCstrRule()),rule.getPlanCstrValue());
                    if(!flag)
                    {
                        resultMsg = getResultMsg(rule);
                    }
                    break;
                }
                // 地域 判断 用户的地域->约束规则->约束键值
                case REGION:{
                    flag = checkRule(user.getRegion(),EnumUtils.getEnum(FilterMode.class,rule.getPlanCstrRule()),rule.getPlanCstrValue());
                    if(!flag)
                    {
                        resultMsg = getResultMsg(rule);
                    }
                    break;
                }
                case WORK_YEAR:{
                    long year = compareDate(user.getWorkTime());
                    flag = checkRule(String.valueOf(year),EnumUtils.getEnum(FilterMode.class,rule.getPlanCstrRule()),rule.getPlanCstrValue());
                    if(!flag)
                    {
                        resultMsg = getResultMsg(rule);
                    }
                    break;
                }
                case JOIN_YEAR:{
                    long year = compareDate(user.getJoinTime());
                    flag = checkRule(String.valueOf(year),EnumUtils.getEnum(FilterMode.class,rule.getPlanCstrRule()),rule.getPlanCstrValue());
                    if(!flag)
                    {
                        resultMsg = getResultMsg(rule);
                    }
                    break;
                }
                case ACHIEVEMENTS:{
//                    flag = checkRuleOfAch(scoreList,EnumUtils.getEnum(FilterMode.class,rule.getPlanCstrRule()),rule.getPlanCstrValue());
                    break;
                }
                case CONTRIBUTION:{
                    break;
                }
                case PLAN_NUM:{
                    break;
                }
            }
            if(!flag)
            {
                return resultMsg;
            }
        }

        return resultMsg;
    }

    private String getDictName(String type, String value)
    {
        return sysDictDataMapper.selectDictLabel(type, value);
    }

    private String getResultMsg(PlanConstraint rule)
    {
        return getDictName("plan_constraint_obj",rule.getPlanCstrObj())
                + "应该"
                + getDictName("plan_constraint_rule",rule.getPlanCstrRule())
                + getDictName(RuleTarget.getType(Integer.parseInt(rule.getPlanCstrObj())),rule.getPlanCstrValue());
    }

    private long compareDate(Date date)
    {
        long year = 0;
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:ss:mm");
        Date now = new Date();
        String nowTime = df.format(now);

        String dataTime = df.format(date);

        try {
            Date old = df.parse(dataTime);
            Date today = df.parse(nowTime);

            year = (((today.getTime() - old.getTime()) / (24 * 60 * 60 * 1000))) / 365;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return year;
    }

    private boolean checkRule(String dataValue, FilterMode filterMode, String ruleValue)
    {
        if(StringUtils.isEmpty(dataValue))
        {
            return false;
        }
        boolean resultFlag = true;
        switch(filterMode)
        {
            case startsWith:{
                break;
            }
            case equals:{
                resultFlag = dataValue.equals(ruleValue) ? true : false;
                break;
            }
            case notLess:
                break;
            case notGreater:
                break;
            case notLower: {
                resultFlag = Integer.parseInt(dataValue) >= Integer.parseInt(ruleValue) ? true : false;
                break;
            }
            case contains:
                break;
            case containsAbove: {
                resultFlag = Integer.parseInt(dataValue) >= Integer.parseInt(ruleValue) ? true : false;
                break;
            }
        }
        return resultFlag;
    }

    private boolean checkRuleOfAch(List<ScoreInfo> scoreList, FilterMode filterMode, String ruleValue)
    {
        boolean resultFlag = true;
        switch(filterMode)
        {
            case startsWith:{
                break;
            }
            case equals:{
                for (ScoreInfo score : scoreList)
                {
                    resultFlag = Integer.parseInt(score.getScoreInfo().toString()) == Integer.parseInt(ruleValue)? true : false;
                    if(!resultFlag)
                    {
                        return false;
                    }
                }
                break;
            }
            case notLess:
                break;
            case notGreater:
                break;
            case notLower: {
                for (ScoreInfo score : scoreList)
                {
                    resultFlag = Integer.parseInt(score.getScoreInfo().toString()) >= Integer.parseInt(ruleValue) ? true : false;
                    if(!resultFlag)
                    {
                        return false;
                    }
                }
                break;
            }
            case contains:
                break;
            case containsAbove: {
                for (ScoreInfo score : scoreList)
                {
                    resultFlag = Integer.parseInt(score.getScoreInfo().toString()) >= Integer.parseInt(ruleValue) ? true : false;
                    if(!resultFlag)
                    {
                        return false;
                    }
                }
                break;
            }
        }
        return resultFlag;
    }

}
